package com.apestech.framework.xml.pub;

import java.io.File;
import java.io.FileOutputStream;
import java.io.StringReader;
import java.util.StringTokenizer;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

import com.apestech.framework.util.FileUtil;
import com.apestech.framework.xml.pub.core.ElementUtil;
import org.xml.sax.InputSource;

/**
 * 读写XML基础类
 * @author hupo
 *
 */
public class ReadXml extends ElementUtil {
	
	private static final Logger logger = Logger.getLogger(ReadXml.class);
	
	private Document document;
	private String xmlHead="<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
	private String xmlRootHead="<YuanYuanSoftware>";
	private String xmlRootTail="</YuanYuanSoftware>";
	
	/**
	 * 字串方式加载XML文件
	 * @return
	 * @throws Exception
	 */
	public Document loadXmlFromString(String xmlStr, boolean hasHead) throws Exception {
		String sXml=xmlStr.trim();
		if(!hasHead){
			sXml=this.xmlHead+this.xmlRootHead+sXml+this.xmlRootTail;
		}
		try {
			document = parseText(sXml);
			return document;
		} catch (DocumentException e) {
			throw new Exception(getMessage("load_xml_error","读取XML失败:\r    "+e.getMessage()+"\r"+sXml));
		}		
	}

	private Document parseText(String text) throws Exception {
		Document result = null;
		SAXReader reader = new SAXReader();
		reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
		reader.setValidation(false);
		String encoding = getEncoding(text);
		InputSource source = new InputSource(new StringReader(text));
		source.setEncoding(encoding);
		result = reader.read(source);
		if (result.getXMLEncoding() == null) {
			result.setXMLEncoding(encoding);
		}
		return result;
	}

	private String getEncoding(String text) {
		String result = null;
		String xml = text.trim();
		if (xml.startsWith("<?xml")) {
			int end = xml.indexOf("?>");
			String sub = xml.substring(0, end);
			StringTokenizer tokens = new StringTokenizer(sub, " =\"'");

			while(tokens.hasMoreTokens()) {
				String token = tokens.nextToken();
				if ("encoding".equals(token)) {
					if (tokens.hasMoreTokens()) {
						result = tokens.nextToken();
					}
					break;
				}
			}
		}
		return result;
	}

	/**
	 * 文件方式加载XML文件
	 * @return
	 * @throws Exception
	 */
	public Document loadXmlFromFile(String fieldName) throws Exception{
		SAXReader reader = new SAXReader();  
		try {
			reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
			reader.setValidation(false);
			document = reader.read(new File(fieldName));
			return document;
		} catch (DocumentException e) {
			throw new Exception(getMessage("load_xml_error","读取XML失败:\r    "+e.getMessage()));
		} 
	}

	public Element getRoot(){
		return document.getRootElement();
	}

	/**
	 * 将原XML经处理之后,生成新的XML
	 * @param node     Element
	 * @param filename String
	 * @throws Exception
	 */
	public void createXML(Element node, String filename) throws Exception{
		Document doc;
		String sXML="";
		String rootName=document.getRootElement().getName().trim();
		if(!this.xmlHead.equals("")){
			sXML=this.xmlHead+"<"+rootName+"></"+rootName+">";
		}
		try {
			doc = DocumentHelper.parseText(sXML);
			Element root=doc.getRootElement();
			copyNode(node, root, false);
			OutputFormat xmlFormat = new OutputFormat();  
	        xmlFormat.setNewlines(true); // 设置换行 
	        xmlFormat.setIndent(true);  // 生成缩进  
	        xmlFormat.setIndent("    ");  // 使用4个空格进行缩进, 可以兼容文本编辑器  
	        FileUtil.createDir(filename);
	        XMLWriter writer = new XMLWriter(new FileOutputStream(filename),xmlFormat); 
			writer.write(doc);  
			writer.close();
		} catch (DocumentException e) {
			throw new Exception(getMessage("create_xml_error","创建XML失败:\r    "+e.getMessage()));
		}
	}

}

